package com.riteny.generator.json2obj;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

/**
 * @author Riteny
 * 2022/1/14  14:54
 */
public class JsonToObject {

    public static String parseJsonObject(String packageName, String outPutDic, String title, JSONObject jsonObject) throws ClassNotFoundException, IOException {

        //首字母大寫的類名
        String className = title.substring(0, 1).toUpperCase() + title.substring(1);

        List<String> importClasses = new LinkedList<>();

        StringBuilder fieldStr = new StringBuilder();
        Iterator keySet = jsonObject.keys();

        while (keySet.hasNext()) {

            String fieldName = keySet.next().toString();
            Object value = jsonObject.opt(fieldName);

            if (value.getClass().equals(JSONArray.class)) {
                //處理數組對象
                String clazzStr = parseJsonArr(packageName, outPutDic, fieldName, JSONArray.fromObject(value));
                fieldStr.append("   private " + "List<" + clazzStr.substring(clazzStr.lastIndexOf(".") + 1) + ">")
                        .append(" ").append(fieldName).append("; \r\n\r\n");
                importClasses.add(clazzStr);
                importClasses.add("java.util.List");
            } else if (value.getClass().equals(JSONObject.class)) {
                /*
                 * 處理json對象，將json對象轉換為java類
                 * 並將轉換成功后的類路徑添加到import list裏面
                 */
                String clazzStr = parseJsonObject(packageName, outPutDic, fieldName, JSONObject.fromObject(value));
                fieldStr.append("   private ").append(clazzStr.substring(clazzStr.lastIndexOf(".") + 1)).append(" ").append(fieldName).append("; \r\n\r\n");
                importClasses.add(clazzStr);
            } else {
                //普通基本類型
                fieldStr.append("   private ").append(value.getClass().getSimpleName()).append(" ").append(fieldName).append("; \r\n\r\n");
                //假如不是基本類型，添加到import
                if (!value.getClass().getName().contains("java.lang")) {
                    importClasses.add(value.getClass().getName());
                }
            }
        }

        String classContext = getJavaClassStr(packageName, className, importClasses, fieldStr.toString());

        return writeJavaClassContextToFile(packageName, outPutDic, className, classContext);
    }


    public static String parseJsonArr(String packageName, String outPutDic, String title, JSONArray jsonArray) throws IOException, ClassNotFoundException {

        String typeClassName = Object.class.getName();

        //檢查數組内對象是否格式統一
        Set<Class> classes = new LinkedHashSet<>();

        jsonArray.stream().forEach(item -> classes.add(item.getClass()));

        if (classes.size() == 1) {

            Class clazz = classes.iterator().next();

            if (clazz.equals(JSONObject.class)) {
                typeClassName = parseJsonObject(packageName, outPutDic, Inflector.getInstance().singularize(title), JSONObject.fromObject(jsonArray.get(0)));
            }
        }

        return typeClassName;
    }


    private static String getJavaClassStr(String packageName, String className, List<String> classes, String fieldStr) {

        StringBuffer classStr = new StringBuffer();

        //生成 import位置
        classStr.append("package ").append(packageName).append(";\r\n\r\n");
        classStr.append("import lombok.Data;\r\n");
        classes.forEach(c -> classStr.append("import ").append(c).append(";\r\n"));

        //生成 class body

        classStr.append("\n@Data\r\n");
        classStr.append("public class ").append(className).append("{\r\n\r\n");
        classStr.append(fieldStr);
        classStr.append("}");

        return classStr.toString();
    }

    private static String writeJavaClassContextToFile(String packageName, String outPutDic, String className, String classContext) throws IOException {

        File file = new File(outPutDic + className + ".java");
        if (!file.exists()) {
            file.createNewFile();
        }

        try (FileWriter fileWriter = new FileWriter(file)) {
            fileWriter.append(classContext);
        }

        return packageName + "." + className;
    }

    public static String createFolder(String outPath, String packageName) {

        String[] dics = packageName.split("\\.");
        File file = new File(outPath);
        for (String dic : dics) {
            file = new File(file.getAbsoluteFile() + "\\" + dic);
            if (!file.exists()) {
                file.mkdir();
            }
        }

        return file.getAbsolutePath() + "\\";
    }


}
